// File: jmcomic-core/src/main/java/dev/jukomu/common/util/net/ProxyBuilder.java
package dev.jukomu.common.util.net;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ProxyBuilder {

    private static final String ADDR_FORMAT = "%s:%s";
    private static final Pattern HOST_PORT_PATTERN = Pattern.compile("^(?:(?:http|https|socks)://)?([^:]+):(\\d+)$");

    /**
     * 构建一个通用代理配置Map。
     *
     * @param address 代理地址，例如 "127.0.0.1:8888" 或 "http://127.0.0.1:8888" 或 "socks://127.0.0.1:7890"
     * @return 代理配置Map，key为协议（http, https, socks），value为完整代理地址字符串。
     * 例如 {"http": "http://127.0.0.1:8888", "https": "http://127.0.0.1:8888"}
     * 或 {"socks": "socks://127.0.0.1:7890"}
     */
    public static Map<String, String> buildProxy(String address) {
        if (address == null || address.isEmpty()) {
            return new HashMap<>();
        }

        Map<String, String> proxies = new HashMap<>();
        String lowerCaseAddress = address.toLowerCase();

        if (lowerCaseAddress.startsWith("http://")) {
            proxies.put("http", address);
            proxies.put("https", address); // Python behavior: HTTPS traffic through HTTP proxy
        } else if (lowerCaseAddress.startsWith("https://")) {
            proxies.put("https", address);
            // In OkHttp, an HTTPS proxy works for both HTTP and HTTPS, but for Python's direct map,
            // we'll keep it explicit based on input protocol.
            // If HTTP_PROXY is https://, Python doesn't implicitly set HTTP.
            // For simplicity and common use, if it's HTTPS proxy, it typically handles HTTP too.
            // However, sticking to Python's dictionary mapping, we'll only set 'https'
        } else if (lowerCaseAddress.startsWith("socks://")) {
            proxies.put("socks", address);
        } else {
            // Assume it's host:port format, default to http proxy
            // We need to validate format, e.g. "127.0.0.1:8888"
            Matcher matcher = HOST_PORT_PATTERN.matcher(address);
            if (matcher.matches()) {
                String host = matcher.group(1);
                String port = matcher.group(2);
                String httpAddress = "http://" + host + ":" + port;
                proxies.put("http", httpAddress);
                proxies.put("https", httpAddress);
            } else {
                throw new IllegalArgumentException("Invalid proxy address format: " + address);
            }
        }
        return proxies;
    }

    /**
     * 构建一个Clash代理配置（通常为SOCKS5）。
     *
     * @param ip   IP地址，默认为 "127.0.0.1"
     * @param port 端口，默认为 "7890"
     * @return 代理配置Map
     */
    public static Map<String, String> clashProxy(String ip, String port) {
        return buildProxy("socks://" + String.format(ADDR_FORMAT, ip, port));
    }

    /**
     * 构建一个Clash代理配置（使用默认IP和端口）。
     *
     * @return 代理配置Map
     */
    public static Map<String, String> clashProxy() {
        return clashProxy("127.0.0.1", "7890");
    }

    /**
     * 构建一个V2Ray代理配置（通常为SOCKS5）。
     *
     * @param ip   IP地址，默认为 "127.0.0.1"
     * @param port 端口，默认为 "10809"
     * @return 代理配置Map
     */
    public static Map<String, String> v2rayProxy(String ip, String port) {
        return buildProxy("socks://" + String.format(ADDR_FORMAT, ip, port));
    }

    /**
     * 构建一个V2Ray代理配置（使用默认IP和端口）。
     *
     * @return 代理配置Map
     */
    public static Map<String, String> v2rayProxy() {
        return v2rayProxy("127.0.0.0.1", "10809");
    }

    /**
     * 构建一个Fiddler代理配置（通常为HTTP）。
     *
     * @param ip   IP地址，默认为 "127.0.0.1"
     * @param port 端口，默认为 "8888"
     * @return 代理配置Map
     */
    public static Map<String, String> fiddlerProxy(String ip, String port) {
        return buildProxy("http://" + String.format(ADDR_FORMAT, ip, port));
    }

    /**
     * 构建一个Fiddler代理配置（使用默认IP和端口）。
     *
     * @return 代理配置Map
     */
    public static Map<String, String> fiddlerProxy() {
        return fiddlerProxy("127.0.0.1", "8888");
    }

    /**
     * 尝试检测并构建系统代理配置。
     * 该方法会检查Java系统属性和环境变量。
     * 注意：Java的系统代理检测能力不如Python的urllib库全面，尤其在跨平台方面。
     * 它不会解析PAC文件或读取复杂的操作系统特定配置。
     *
     * @return 代理配置Map，如果未检测到代理则返回空Map
     */
    public static Map<String, String> systemProxy() {
        Map<String, String> proxies = new HashMap<>();

        // 1. 检查Java系统属性
        // http proxy
        String httpHost = System.getProperty("http.proxyHost");
        String httpPort = System.getProperty("http.proxyPort");
        if (httpHost != null && !httpHost.isEmpty() && httpPort != null && !httpPort.isEmpty()) {
            String proxyAddr = "http://" + httpHost + ":" + httpPort;
            proxies.put("http", proxyAddr);
            // If HTTPS proxy is not explicitly set, assume it also uses the HTTP proxy (Python behavior)
            if (System.getProperty("https.proxyHost") == null || System.getProperty("https.proxyHost").isEmpty()) {
                proxies.put("https", proxyAddr);
            }
        }

        // https proxy
        String httpsHost = System.getProperty("https.proxyHost");
        String httpsPort = System.getProperty("https.proxyPort");
        if (httpsHost != null && !httpsHost.isEmpty() && httpsPort != null && !httpsPort.isEmpty()) {
            proxies.put("https", "http://" + httpsHost + ":" + httpsPort); // Python: HTTPS via HTTP proxy
        }

        // socks proxy
        String socksHost = System.getProperty("socksProxyHost");
        String socksPort = System.getProperty("socksProxyPort");
        if (socksHost != null && !socksHost.isEmpty() && socksPort != null && !socksPort.isEmpty()) {
            proxies.put("socks", "socks://" + socksHost + ":" + socksPort);
        }

        // 2. 如果系统属性未设置代理，尝试检查环境变量
        if (proxies.isEmpty()) {
            String httpProxyEnv = System.getenv("HTTP_PROXY");
            String httpsProxyEnv = System.getenv("HTTPS_PROXY");
            String allProxyEnv = System.getenv("ALL_PROXY"); // Common for SOCKS/HTTP/HTTPS

            if (httpProxyEnv != null && !httpProxyEnv.isEmpty()) {
                proxies.put("http", httpProxyEnv);
                if (httpsProxyEnv == null || httpsProxyEnv.isEmpty()) {
                    // Python's urllib behavior is to try http_proxy for https as well if https_proxy is not set.
                    // This simple replacement might not always be correct for HTTPS proxies,
                    // but it aligns with the Python example's general behavior of sharing.
                    proxies.put("https", httpProxyEnv.replaceFirst("^http://", "https://"));
                }
            }
            if (httpsProxyEnv != null && !httpsProxyEnv.isEmpty()) {
                proxies.put("https", httpsProxyEnv);
            }

            if (allProxyEnv != null && !allProxyEnv.isEmpty()) {
                if (allProxyEnv.startsWith("socks://")) {
                    proxies.put("socks", allProxyEnv);
                } else if (allProxyEnv.startsWith("http://") || allProxyEnv.startsWith("https://")) {
                    // If it's an all-encompassing HTTP/HTTPS proxy, set for both
                    if (!proxies.containsKey("http")) proxies.put("http", allProxyEnv);
                    if (!proxies.containsKey("https")) proxies.put("https", allProxyEnv);
                } else {
                    // Fallback for host:port in ALL_PROXY assumed to be HTTP
                    if (!proxies.containsKey("http")) proxies.put("http", "http://" + allProxyEnv);
                    if (!proxies.containsKey("https")) proxies.put("https", "http://" + allProxyEnv);
                }
            }
        }

        return proxies;
    }

    /**
     * 根据字符串构建代理配置。
     * 支持 "127.0.0.1:1234" / "clash" / "v2ray" / "fiddler" / "system"。
     *
     * @param text 代理字符串
     * @return 代理配置Map
     */
    public static Map<String, String> buildByStr(String text) {
        if (text == null || text.isEmpty()) {
            return new HashMap<>();
        }

        String lowerCaseText = text.toLowerCase();

        // Check for special keywords
        switch (lowerCaseText) {
            case "clash":
                return clashProxy();
            case "v2ray":
                return v2rayProxy();
            case "fiddler":
                return fiddlerProxy();
            case "system":
                return systemProxy();
            default:
                // Assume it's a direct address, let buildProxy handle protocol detection
                // Python's build_by_str directly passes 'text' to build_proxy(text) if not a keyword.
                // Our buildProxy handles "http://host:port", "socks://host:port", or "host:port"
                return buildProxy(text);
        }
    }
}